<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="ls2CR" id="ls2CR"><span data-lake-id="u447025f7" id="u447025f7">典型回答</span></h1>
  <p data-lake-id="ua65fda21" id="ua65fda21"><br></p>
  <p data-lake-id="u1ade2591" id="u1ade2591"><span data-lake-id="u2bc357f7" id="u2bc357f7">想要定位一个接口响应慢，有一个神器必备，那就是阿里巴巴推出的arthas，很快的就能定位到接口RT慢的问题，具体有一个案例，大家可以看下：</span></p>
  <p data-lake-id="uffa653ed" id="uffa653ed"><span data-lake-id="u2249784f" id="u2249784f">​</span><br></p>
  <p data-lake-id="uf9c540c0" id="uf9c540c0"><br></p>
  <p data-lake-id="u221b145a" id="u221b145a"><span data-lake-id="u2ae4f168" id="u2ae4f168">使用Arthas定位接口慢的步骤大致如下：</span></p>
  <p data-lake-id="u8df43708" id="u8df43708"><span data-lake-id="u176b443a" id="u176b443a">​</span><br></p>
  <p data-lake-id="u2ad80da5" id="u2ad80da5"><strong><span data-lake-id="u2a1be0cb" id="u2a1be0cb">1、首先就是通过各种监控系统，发现慢的现象或者问题。</span></strong><span data-lake-id="u8c26ad7c" id="u8c26ad7c">我们明确的知道了具体是哪个接口慢了。然后才能开始分析。</span></p>
  <p data-lake-id="u2ff2263e" id="u2ff2263e"><span data-lake-id="uc92c451b" id="uc92c451b">​</span><br></p>
  <p data-lake-id="u2c9d5083" id="u2c9d5083"><strong><span data-lake-id="uf9e4d785" id="uf9e4d785">2、安装arthas，</span></strong><span data-lake-id="u310cc63e" id="u310cc63e">arthas就是一个命令工具，他通过字节码插桩的方式来统计接口耗时的，很多公司的生产环境也都是可以用的，包括我司的生产环境都是可以用的，目前没发现什么副作用。</span></p>
  <p data-lake-id="ub1c2f2db" id="ub1c2f2db"><span data-lake-id="u6d566891" id="u6d566891">​</span><br></p>
  <pre lang="java"><code>
curl -L http://start.alibaba-inc.com/install.sh | sh
</code></pre>
  <p data-lake-id="u9c59c2ed" id="u9c59c2ed"><br></p>
  <p data-lake-id="ud5b5e92c" id="ud5b5e92c"><span data-lake-id="ua3d7fe20" id="ua3d7fe20">以上命令即可安装。</span></p>
  <p data-lake-id="u7f510bed" id="u7f510bed"><span data-lake-id="u5ba4c30a" id="u5ba4c30a">​</span><br></p>
  <p data-lake-id="u30dce215" id="u30dce215"><strong><span data-lake-id="u3c37da29" id="u3c37da29">3、运行，</span></strong><span data-lake-id="ue5227f10" id="ue5227f10">比较简单，执行命令就行：</span></p>
  <p data-lake-id="u6b314480" id="u6b314480"><span data-lake-id="ufa219b73" id="ufa219b73">​</span><br></p>
  <pre lang="java"><code>
sh as.sh 
</code></pre>
  <p data-lake-id="uf315a80f" id="uf315a80f"><br></p>
  <p data-lake-id="ufd357fe1" id="ufd357fe1"><strong><span data-lake-id="u81eed3f0" id="u81eed3f0">4、查看接口耗时</span></strong><span data-lake-id="u1a60a35c" id="u1a60a35c">，这个就需要借助arthas的trace命令了，详见 </span><a href="https://arthas.aliyun.com/" target="_blank" data-lake-id="ud7a4f432" id="ud7a4f432"><span data-lake-id="ud28e36c0" id="ud28e36c0">https://arthas.aliyun.com/</span></a><span data-lake-id="ua6fc4890" id="ua6fc4890"> 官网，trace命令的主要作用就是查看方法内部调用路径，并输出方法路径上的每个节点上耗时。</span></p>
  <p data-lake-id="ubc06a2c7" id="ubc06a2c7"><span data-lake-id="ud9ed0846" id="ud9ed0846">​</span><br></p>
  <p data-lake-id="ud47c806f" id="ud47c806f"><span data-lake-id="u5b045ca4" id="u5b045ca4">参数说明如下：</span></p>
  <p data-lake-id="ua6feb426" id="ua6feb426"><span data-lake-id="uaeb09770" id="uaeb09770">​</span><br></p>
  <p data-lake-id="u317d0f00" id="u317d0f00"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1686917575215-ab4d6089-ea23-4b4f-a887-c4dbf9104cf0.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_41%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ue9f7e2ef" id="ue9f7e2ef"><br></p>
  <p data-lake-id="ub7262a90" id="ub7262a90"><br></p>
  <p data-lake-id="u0180ca80" id="u0180ca80"><span data-lake-id="u89b2c2fa" id="u89b2c2fa">比如直接查看一次真实请求的耗时情况（例子来自官网，大家可以自己实践一下）：</span></p>
  <p data-lake-id="ube96066e" id="ube96066e"><span data-lake-id="u1219178d" id="u1219178d">​</span><br></p>
  <pre lang="java"><code>
$ trace demo.MathGame run
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 28 ms.
`---ts=2019-12-04 00:45:08;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
    `---[0.617465ms] demo.MathGame:run()
        `---[0.078946ms] demo.MathGame:primeFactors() #24 [throws Exception]

`---ts=2019-12-04 00:45:09;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
    `---[1.276874ms] demo.MathGame:run()
        `---[0.03752ms] demo.MathGame:primeFactors() #24 [throws Exception]
</code></pre>
  <p data-lake-id="u7939acd9" id="u7939acd9"><br></p>
  <p data-lake-id="u07a2e112" id="u07a2e112"><span data-lake-id="ucce3e08d" id="ucce3e08d">如果方法调用的次数很多，那么可以用-n参数指定捕捉结果的次数。比如下面的例子里，捕捉到一次调用就退出命令：</span></p>
  <p data-lake-id="uc397e6ff" id="uc397e6ff"><span data-lake-id="ub670db56" id="ub670db56">​</span><br></p>
  <pre lang="java"><code>
$ trace demo.MathGame run -n 1
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 20 ms.
`---ts=2019-12-04 00:45:53;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
    `---[0.549379ms] demo.MathGame:run()
        +---[0.059839ms] demo.MathGame:primeFactors() #24
        `---[0.232887ms] demo.MathGame:print() #25

Command execution times exceed limit: 1, so command will exit. You can set it with -n option.

</code></pre>
  <p data-lake-id="u5f172c64" id="u5f172c64"><br></p>
  <p data-lake-id="uaba09cb3" id="uaba09cb3"><span data-lake-id="u70450592" id="u70450592">也可以做一些过滤，比如耗时超过一定时长的再进行观测：</span></p>
  <p data-lake-id="u9d866b2d" id="u9d866b2d"><span data-lake-id="uabf174c2" id="uabf174c2">​</span><br></p>
  <pre lang="java"><code>
$ trace demo.MathGame run '#cost &gt; 1000'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 41 ms.
`---ts=2018-12-04 01:12:02;thread_name=main;id=1;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@3d4eac69
    `---[12.033735ms] demo.MathGame:run()
        +---[0.006783ms] java.util.Random:nextInt()
        +---[11.852594ms] demo.MathGame:primeFactors()
        `---[0.05447ms] demo.MathGame:print()

</code></pre>
  <p data-lake-id="u00f75323" id="u00f75323"><span data-lake-id="u8ab9325d" id="u8ab9325d">以上就是只观测耗时超过1000Ms的请求。</span></p>
  <p data-lake-id="ub9273b10" id="ub9273b10"><span data-lake-id="u94e64e4e" id="u94e64e4e">​</span><br></p>
  <p data-lake-id="u2225d699" id="u2225d699"><strong><span data-lake-id="u9a8a0b98" id="u9a8a0b98">5、分析耗时。</span></strong></p>
  <p data-lake-id="u69a44dd2" id="u69a44dd2"><span data-lake-id="u5ff267be" id="u5ff267be">​</span><br></p>
  <p data-lake-id="uc632d99b" id="uc632d99b"><span data-lake-id="udcd4d5de" id="udcd4d5de">如下面一个trace的输出信息，可以看到，一个借口整体耗时在265ms左右，但是其中有221ms是耗时在com.alibaba.fin.pricing.*.ExercisePriceDomainService:queryMatchedEffectiveExercisePrice() #167 这里的，所以就可以直接去看代码，分析下这里为什么有耗时了。</span></p>
  <p data-lake-id="u1083e249" id="u1083e249"><span data-lake-id="ua55cd09d" id="ua55cd09d">​</span><br></p>
  <pre lang="java"><code>
[arthas@1658]$ trace com.alibaba.fin.pricing.**.PriceCalculateService trial '#cost &gt; 50' -n 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 427 ms, listenerId: 6
`---ts=2021-11-08 15:10:24;thread_name=HSFBizProcessor-DEFAULT-8-thread-224;id=2d7c1;is_daemon=true;priority=10;TCCL=com.taobao.pandora.boot.loader.LaunchedURLClassLoader@783e6358;trace_id=2132e43116363554229592404e58b8;rpc_id=9.40.6
    `---[264.85838ms] com.alibaba.fin.pricing.**.service.PriceCalculateService:trial()
        +---[0.012009ms] com.alibaba.fin.pricing.**.request.PriceCalculateRequest:getTenant() #95
        +---[0.001564ms] com.alibaba.fin.pricing.**.request.PriceCalculateRequest:getProduct() #96
        ...
        ...
        ...
        +---[221.884809ms] com.alibaba.fin.pricing.*.ExercisePriceDomainService:queryMatchedEffectiveExercisePrice() #167
        +---[0.002242ms] com.alibaba.fin.pricing.**.service.PriceQueryRequest:&lt;init&gt;() #170
        `---[0.012586ms] com.alibaba.fin.pricing.**.service.PriceCalculateService:getTieredPrice() #170
</code></pre>
  <p data-lake-id="u8f99b0f2" id="u8f99b0f2"><span data-lake-id="u29c028c7" id="u29c028c7">​</span><br></p>
  <p data-lake-id="u7acbcd8a" id="u7acbcd8a"><strong><span data-lake-id="u50012eff" id="u50012eff">6、耗时优化，</span></strong><span data-lake-id="u858bc12c" id="u858bc12c">在定位到具体耗时的代码时，就可以分析了，是请求执行慢了，还是SQL慢了，还是哪里慢了，然后就想办法优化：</span></p>
  <p data-lake-id="u766fc286" id="u766fc286"><span data-lake-id="u01cb9183" id="u01cb9183">​</span><br></p>
  <p data-lake-id="u0f4988af" id="u0f4988af"><a href="https://www.yuque.com/hollis666/vhr2ge/ifuuagaqo3yd8vqb" data-lake-id="uec090795" id="uec090795"><span data-lake-id="u3e45b522" id="u3e45b522">https://www.yuque.com/hollis666/vhr2ge/ifuuagaqo3yd8vqb</span></a></p>
  <p data-lake-id="u7a634e52" id="u7a634e52"><a href="https://www.yuque.com/hollis666/vhr2ge/mgpczmz7la99dkft" data-lake-id="uc50bc7e8" id="uc50bc7e8"><span data-lake-id="uae03e88f" id="uae03e88f">https://www.yuque.com/hollis666/vhr2ge/mgpczmz7la99dkft</span></a></p>
  <p data-lake-id="u75d2b256" id="u75d2b256"><a href="https://www.yuque.com/hollis666/vhr2ge/zhfa5g" data-lake-id="ufdbc9bf8" id="ufdbc9bf8"><span data-lake-id="u692debbe" id="u692debbe">https://www.yuque.com/hollis666/vhr2ge/zhfa5g</span></a></p>
 </body>
</html>